// ignore: implementation_imports, import_of_legacy_library_into_null_safe
import 'package:build/src/builder/build_step.dart';
import 'package:analyzer/dart/element/element.dart' as ele;

// ignore: import_of_legacy_library_into_null_safe
import 'package:source_gen/source_gen.dart';

// ignore: import_of_legacy_library_into_null_safe
import 'package:build/build.dart';
import 'package:xanno/src/anno/utils/pars_params.dart';
import 'dart:io';
import 'size.dart';
import 'tpl/tpl.dart' as tpl;
import 'package:xanno/src/anno/project/tpl/tpl_utils_screen_util.dart'
    as tpl_screen_util;

enum RegType {
  px,
  sp,
  pix,
}

class SizeGenerator extends GeneratorForAnnotation<GSize> {
  final separator = Platform.pathSeparator;
  Map<String, String> sizeMap = {};

  //记录之前生成的配置
  Map<String, String> updateSizeMap = {};

  //记录有效
  Map<String, String> effectiveMap = {};
  List sizeRegs = [
    {"reg": r"\d+(\.)?(\d+)?\.px", "type": RegType.px},
    {"reg": r"\d+(\.)?(\d+)?\.sp", "type": RegType.sp},
    {"reg": r"\d+(\.)?(\d+)?\.pix", "type": RegType.pix},
  ];
  List ignores = [
    '.size.dart',
  ];

  void readFile(path) {
    try {
      File file = File(path);
      bool exists = file.existsSync();
      if (exists) {
        //文件存在
        var lines = file.readAsLinesSync();
        lines.forEach((line) {
          RegExp(r"static double.*").allMatches(line).forEach((v) {
            String cStr = v.group(0)!;
            var arr = cStr.substring(0, cStr.length - 1).split(' = ');
            var key = arr.first.split(' ').last;
            var value = arr.last;
            updateSizeMap[key] = value;
          });
        });
      }
    } catch (e) {
      stdout.writeln('读取文件失败! $path $e');
    }
  }

  void updateFiles(String root, {package, required String importStr}) {
    try {
      var directory = Directory(root);
      List<FileSystemEntity> files = directory.listSync();
      files.forEach((f) async {
        var bool = FileSystemEntity.isFileSync(f.path);
        if (!bool) {
          updateFiles(f.path, package: package, importStr: importStr);
        } else {
          ///之后可以通过文件hash 来判断文件是否被变化，提高效率
          var ignoreItem;
          try {
            ignoreItem =
                ignores.firstWhere((element) => f.path.endsWith(element));
          } catch (e) {}
          if (ignoreItem == null && f.path.endsWith('.dart')) {
            await updateSizeLine(f.path,
                package: package, importStr: importStr);
          }
        }
      });
    } catch (e) {
      stdout.writeln("目录不存在！$root");
    }
  }

  updateSizeLine(path, {package, required String importStr}) async {
    try {
      File file = File(path);
      var lines = file.readAsLinesSync();
      var newLines = [];
      //文件是否被匹配到最少一次
      bool fileFlag = false;
      //import
      bool importFlag = true;
      lines.forEach((line) {
        if (line.trim() == importStr) {
          importFlag = false;
        }
        //查看原有生成的是否还存在
        updateSizeMap.forEach((key, value) {
          if (line.contains(key)) {
            //记录有效
            effectiveMap[key] = value;
          }
        });

        var newLine = line;
        bool preFlag = false;
        bool childFlag = false;
        sizeRegs.forEach((regObj) {
          var reg = regObj['reg'];
          var type = regObj['type'];
          RegExp(reg).allMatches(line).forEach((v) {
            //起码匹配过一次
            preFlag = true;
            childFlag = true;
            fileFlag = true;
            String sizeValue = v.group(0)!;
            String? sizeKey = getSizeKey(type, sizeValue);
            if (sizeKey != null) {
              sizeMap[sizeKey] = sizeValue;
              newLine = newLine.replaceAll(sizeValue, 'SizeConstant.$sizeKey');
            }
          });
        });
        if (childFlag) {
          // colorRegs匹配到才添加
          newLines.add(newLine);
        }
        if (!preFlag) {
          //一次没匹配过
          newLines.add(newLine);
        }
      });

      //将有效配置，存入sizeMap
      effectiveMap.forEach((key, value) {
        sizeMap[key] = value;
      });

      if (fileFlag && importFlag) {
        //最少匹配到一个， 导入import
        newLines.insert(0, importStr);
      }

      var sb = StringBuffer();
      newLines.forEach((line) {
        sb.writeln(line);
      });

      ///写入文件
      await file.writeAsString(sb.toString());
    } catch (e) {
      stdout.writeln('读取文件失败! $path $e');
    }
  }

  String? getSizeKey(type, String colorValue) {
    String? sizeKey;
    switch (type) {
      case RegType.px:
        sizeKey = 'size_px_' +
            colorValue.substring(0, colorValue.length - 3).replaceAll('.', 'X');
        break;
      case RegType.sp:
        sizeKey = 'size_sp_' +
            colorValue.substring(0, colorValue.length - 3).replaceAll('.', 'X');
        break;
      case RegType.pix:
        sizeKey = 'size_pix_' +
            colorValue.substring(0, colorValue.length - 4).replaceAll('.', 'X');
        break;
      default:
        sizeKey = null;
        break;
    }
    return sizeKey;
  }

  String buildConstant(Map<String, String> map) {
    //处理map中px/sp/pix
    var sb = StringBuffer();
    var pxMap = {};
    var spMap = {};
    var pixMap = {};
    Function writeData = (Map map, StringBuffer sb) {
      map.forEach((key, value) {
        sb.writeln("  // ignore: non_constant_identifier_names");
        sb.writeln("  static double $key = $value;");
      });
    };
    map.forEach((key, value) {
      if (key.startsWith('size_px_')) {
        pxMap[key] = value;
      }
      if (key.startsWith('size_sp_')) {
        spMap[key] = value;
      }
      if (key.startsWith('size_pix_')) {
        pixMap[key] = value;
      }
    });
    sb.writeln();
    sb.writeln("  /// px 常量");
    writeData(pxMap, sb);
    sb.writeln();
    sb.writeln("  /// sp 常量");
    writeData(spMap, sb);
    sb.writeln();
    sb.writeln("  /// pix 常量");
    writeData(pixMap, sb);
    return sb.toString();
  }

  @override
  generateForAnnotatedElement(
      ele.Element element, ConstantReader annotation, BuildStep buildStep) {
    final map = ParsParams.pars(
        annotation, {'enable': false, 'dir': '', 'name': '', 'suffix': ''});
    bool enable = map['enable'];
    String dir = map['dir'];
    String name = map['name'];
    String suffix = map['suffix'];
    if (!enable) return null;

    String fileDir = dir.split('/').join(separator);
    String fileName = '$separator$name';
    String impDir = dir.split('/').skip(1).join('/');
    String importStr =
        "import 'package:${buildStep.inputId.package}/$impDir/$name$suffix';";

    if (enable) {
      //生成工具类
      var exists =
          Directory('${Directory.current.path}${separator}lib${separator}utils')
              .existsSync();
      if (exists) {
        var file = File(
            '${Directory.current.path}${separator}lib${separator}utils${separator}screen_util.dart');
        if (!file.existsSync()) {
          //文件不存在，生成
          File('${Directory.current.path}${separator}lib${separator}utils${separator}screen_util.dart')
              .writeAsStringSync(tpl_screen_util.clazzTpl(
            package: buildStep.inputId.package,
          ));
        }
      } else {
        File(
            '${Directory.current.path}${separator}lib${separator}utils${separator}screen_util.dart')
          ..createSync(recursive: true)
          ..writeAsStringSync(tpl_screen_util.clazzTpl(
            package: buildStep.inputId.package,
          ));
      }
    }
    //读取已经生成的文件配置
    readFile('${Directory.current.path}$separator$fileDir$fileName$suffix');
    //查找size并修改文件
    updateFiles('${Directory.current.path}${separator}lib',
        package: buildStep.inputId.package, importStr: importStr);
    //生成SizeConstant class
    File('${Directory.current.path}$separator$fileDir$fileName$suffix')
      ..createSync(recursive: true)
      ..writeAsStringSync(tpl.clazzTpl(
        package: buildStep.inputId.package,
        buildCode: buildConstant(sizeMap),
      ));
    return null;
  }
}

Builder sizeBuilder(BuilderOptions options) =>
    LibraryBuilder(SizeGenerator(), generatedExtension: ".size.dart");
